home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 32
/
Mac Magazin and MacEasy Magazine CD - Issue 32.iso
/
Multimedia
/
MIDI
/
MidiChaos_15 Folder
/
MidiChaos_1.5
/
Source
/
Tools
/
FloatingPoint
< prev
next >
Wrap
Text File
|
1990-09-19
|
10KB
|
482 lines
\ Floating Point Support for H4th
\ Use the SANE system from Apple
\
\ Please see the Standard Apple Numerics manual for more information.
\ This code is based loosely on the upcoming ANSI Forth standard.
\
\ Work remaining:
\ O- Better ANSI compliance
\ O- Optimize stack ops
\
\ *********************************************************************
\ * HMSL Forth System *
\ * Author: Phil Burk *
\ * Copyright 1989 Phil Burk , All Rights Reserved *
\ *********************************************************************
\
\ MOD: 7/12/90 F> and F< now use FLOAT.2->0 to avoid leaving stuff on FSTACK
\ F. smarter about style choices, added EXP.
\ Fixed FLOG, Added FLOG2, sped up FSWAP and FROT
\ MOD: PLB 7/18/90 Added F.R
\ MOD: RDG 9/19/90 Changed fpinit and fpterm to support floating point members.
ANEW TASK-FLOATINGPOINT
decimal
32 constant FLOAT_STACK_SIZE
10 constant FLOAT_WIDTH
create FLOAT-STACK FLOAT_WIDTH FLOAT_STACK_SIZE 2+ * ALLOT
variable FLOAT-STACK-PTR ( pointer to top of floating point stack )
: F0SP ( -- , reset float stack pointer )
\ stack grows up
float-stack float-stack-ptr !
;
f0sp
: FLOAT.CHECK ( -- , check floating point stack )
float-stack-ptr @ dup float-stack <
IF ." Floating Pointing Stack Underflow!" cr f0sp abort
ELSE
float-stack [ float_width float_stack_size * ] literal + >
IF ." Floating Point Stack Overflow!" cr f0sp abort
THEN
THEN
;
: FMOVE ( addr1 addr2 -- , move floating point number , %Q optimize )
float_width cmove
;
: F@ ( addr -- , -f- f , fetch float )
float-stack-ptr @ float_width + dup float-stack-ptr !
fmove
;
: F! ( addr -- , f -f- , store float )
float-stack-ptr @ dup float_width - float-stack-ptr !
swap fmove
;
: FDEPTH ( -- depth , number of items on float stack )
float-stack-ptr @ float-stack - float_width /
;
: FPICK ( n -- , fn ... f1 f0 -- fn ... f1 f0 fn )
[ float_width negate ] literal * float-stack-ptr @ + f@
;
: FVARIABLE ( <name> -- )
CREATE float_width allot
;
fvariable FTEMP \ variable for storing temporary values for stack
: FCONSTANT ( f -f- , <name> -- , make constant )
CREATE here f! float_width allot
DOES> f@
;
: FDROP ( f -f- , DROP floating point value )
[ float_width negate ] literal float-stack-ptr +!
;
: FDUP ( f -f- f f, DUP floating point value )
float-stack-ptr @ f@
;
: FOVER ( fa fb -f- fa fb fa, OVER floating point value )
float-stack-ptr @ float_width - f@
;
: FSWAP ( fa fb -f- fb fa, SWAP floating point value )
float-stack-ptr @ dup ftemp fmove \ fb -> ftemp
dup float_width - dup>r swap fmove \ fa -> top
ftemp r> fmove \ ftemp -> second
;
: FROT ( fa fb fc -f- fb fc fa, ROT floating point value )
float-stack-ptr @ [ float_width 2* ] literal - ftemp fmove
float-stack-ptr @ float_width -
dup float_width - [ float_width 2* ] literal cmove
ftemp float-stack-ptr @ fmove
;
$ A9EB constant T_FP68K
$ A9EC constant T_Elems68K
$ A9EE constant T_DECSTR68K
\ SANE Interface
: CALLSANE ( <number> <trap> -- , compile trap number with # on return stack )
?comp
base @ hex
bl word number?
IF drop $ 3F3C w, w, \ MOVE.S #xx,-(A7)
bl word number?
IF drop w, \ TRAP
ELSE ." callsane - Not a valid number!" abort
THEN
ELSE ." callsane - Not a valid number!" abort
THEN
base !
; immediate
: FLOAT ( n -- , -f- f , convert integer to float on stack )
\ Push address of data stack and drop.
[ $ 2F0E w, \ move.l a6,-(a7)
]
float-stack-ptr @ float_width + dup float-stack-ptr ! >r
callsane 280E A9EB ( FL2X )
drop
;
: INT ( -- n , f -f- , convert float to integer )
float-stack-ptr @ dup float_width - float-stack-ptr ! >r
\ Push address of data stack and drop.
[ $ 598E w, \ subq.l #4,a6
$ 2F0E w, \ move.l a6,-(a7)
]
callsane 2810 A9EB ( FX2L )
;
: F>I ( -- i , f -f- , Mach2 compatible )
int
;
: I>F ( i -- , -- f , Mach2 compatible )
float
;
: FLOAT.2->0 ( -r- $dst $src , setup stack for binary operators )
r> ( save return address )
float-stack-ptr @ dup >r
float_width - dup >r
float_width - float-stack-ptr !
>r ( restore return adress )
;
: FLOAT.2->1 ( -r- $dst $src , setup stack for binary operators )
r> ( save return address )
float-stack-ptr @ dup >r
float_width - dup >r
float-stack-ptr !
>r ( restore return adress )
;
: FLOAT.1->1 ( -- $dst , setup stack for unary operators )
r> ( save return address )
float-stack-ptr @ >r
>r ( restore return adress )
;
: F* ( f1 f2 -- f1*f2 )
float.2->1
callsane 0004 A9EB
;
: F+ ( f1 f2 -- f1+f2 )
float.2->1
callsane 0000 A9EB
;
: F- ( f1 f2 -- f1-f2 )
float.2->1
callsane 0002 A9EB
;
: F/ ( f1 f2 -- f1/f2 )
float.2->1
callsane 0006 A9EB
;
: FSQRT ( f -f- sqrt[f] )
float.1->1
callsane 0012 A9EB
;
: FMOD ( f1 f2 -- rem[f1/f2] )
float.2->1
callsane 000C A9EB
;
: FROUND ( f -f- round[f] )
float.1->1
callsane 0014 A9EB
;
: FTRUNCATE ( f -f- truncate[f] )
float.1->1
callsane 0016 A9EB
;
: FNEGATE ( f -f- -f )
float.1->1
callsane 000D A9EB
;
: FABS ( f -f- abs[f] )
float.1->1
callsane 000F A9EB
;
\ Floating Point Comparisons
: COMPILE.FCOMP ( -- , code fragment for comparison )
$ 42a6 w, \ clr.l -(a6)
$ 4E75 w, \ rts
$ 2D3C w, $ FFFFFFFF , \ move.l #$-1,-(a6)
; immediate
: FCMPX() ( f1 f2 -- )
float.2->0
callsane 0008 A9EB
;
: F> ( f1 f2 -- flag )
fcmpx()
[ $ 6E04 w, ] \ BGT
compile.fcomp
;
: F< ( f1 f2 -- flag )
fcmpx()
[ $ 6D04 w, ] \ BLT
compile.fcomp
;
: F= ( f1 f2 -- flag )
fcmpx()
[ $ 6704 w, ] \ BEQ
compile.fcomp
;
\ Elementary Functions
: FLN ( f -- ln[f] )
float.1->1 callsane 0000 a9ec
;
: FLOG2 ( f -- log2[f] )
float.1->1 callsane 0002 a9ec
;
: FEXP ( f -- exp[f] )
float.1->1 callsane 0008 a9ec
;
: F** ( fx fy -- fx**fy )
float.2->1 callsane 8012 a9ec
;
: FSIN ( f -- sin[f] )
float.1->1 callsane 0018 a9ec
;
: FCOS ( f -- cos[f] )
float.1->1 callsane 001A a9ec
;
: FTAN ( f -- tan[f] )
float.1->1 callsane 001C a9ec
;
: FATAN ( f -- atan[f] )
float.1->1 callsane 001E a9ec
;
: FRANDOM ( f -- random[f] )
float.1->1 callsane 0020 a9ec
;
variable SANE-ENVIRONMENT
: SANE.GETENV ( -- envword , get environmental control word )
sane-environment >r
callsane 0003 A9EB
sane-environment w@
;
: SANE.SETENV ( envword -- , set environmental control word )
sane-environment w!
sane-environment >r
callsane 0001 A9EB
;
:STRUCT DecimalRecord
ushort DR_SGN
short DR_EXP
20 bytes DR_STRING
;STRUCT
:STRUCT DecimalForm
ushort DF_STYLE
ushort DF_DIGITS
;STRUCT
-1 constant FP_DECIMAL_STYLE
0 constant FP_EXP_STYLE
\ Declare stock structures for use with conversion.
DecimalRecord FP-DecRec
DecimalForm FP-DecForm
\ Input Conversion
variable VALID-PREFIX
variable FSTR-OFFSET
: FSTR2DEC ( string -- 1=ok | 0=bad , build decimal record )
>r
1 fstr-offset dup >r w!
fp-decRec >r
valid-prefix >r
callsane 0002 A9EE
valid-prefix c@
;
: FDEC2X ( -f- f , convert record to X )
fp-decrec >r
float-stack-ptr @ float_width + dup >r float-stack-ptr !
callsane 0009 A9EB
float.check
;
: FNUMBER? ( $string -- true | false , -f- f | , convert if valid )
fstr2dec
IF fdec2x true
ELSE false
THEN
;
defer OLD.RECOGNIZE
: (FLIT) ( fnum-inline , -f- f , get from inline, put on f-stack )
r> dup f@
float_width +
>r
;
: F, ( f -f- , compile fnum into dictionary )
here f!
float_width allot
;
: FLITERAL ( f -f- , )
state @
IF compile (flit) f,
THEN
;
: FNUMLIT ( $string -- flag , -f- f , if true )
fnumber? dup
IF fliteral
THEN
;
: FRECOGNIZE ( $string -- flag )
dup old.recognize ( -- $string flag )
IF drop true ( recognized by something else )
ELSE ( -- $string )
base @ $ 10 - ( make sure not in hex mode )
IF dup ascii . index
IF ( -- $string addr ) drop fnumlit
ELSE dup ascii E index
IF drop fnumlit
ELSE drop false
THEN
THEN
ELSE drop false
THEN
THEN
;
variable IF-FP-INIT
: FPINIT ( -- )
f0sp
if-fp-init @ 0=
IF what's recognize is old.recognize
'c frecognize is recognize
'c f! is s.f! \ s.f! and s.f@ are defered in my_struct
'c f@ is s.f@
if-fp-init on
THEN
;
: FPTERM ( -- )
if-fp-init @
IF what's old.recognize is recognize
'c noop dup is s.f! is s.f@ \ reset deferred words
if-fp-init off
THEN
;
fpinit
10.0 flog2 fconstant 10FLOG2
1.0 fatan 4.0 f* fconstant PI
fpterm
: FLOG ( f -f- log[f] , base 10 )
flog2 10flog2 f/
;
\ Output Conversion
: FDec2Str ( -- string )
fp-decForm >r
fp-decRec >r
pad >r
callsane 0003 A9EE
pad
;
: FX2Dec ( f -f- , load stock records )
fp-decForm >r
float-stack-ptr @ dup float_width - float-stack-ptr ! >r
fp-decRec >r
callsane 000B A9EB
;
: PLACES ( n -- , set number of significant or fractional digits )
fp-decform ..! df_digits
;
6 places
: (F>TEXT) ( f -f- , style -- addr count )
float.check
fp-decForm ..! df_style \ force style
fx2dec
fdec2str
count
float.check
;
variable FP-SWITCH
8 FP-SWITCH !
: F>TEXT ( f -f- , -- addr count )
fdup flog fabs int fp-switch @ > 0=
(f>text)
;
: F.R ( f -f- , nchars -- )
>r f>text r> over - 0 max spaces type
;
: EXP.R ( f -f- , nchars -- )
>r fp_exp_style (f>text) r> over - 0 max spaces type
;
: F. ( f -f- )
f>text type space
;
: EXP. ( f -f- )
fp_exp_style (f>text) type space
;
: F.S ( -- dump floating point stack )
>newline fdepth 0>
IF fdepth float_stack_size >
IF ." Float Stack Overflow!" f0sp abort
ELSE ." FPStack: " fdepth 0
DO fdepth i - 1- fpick f. cr?
LOOP
THEN
ELSE fdepth 0=
IF ." Float Stack Empty"
ELSE ." Float Stack Underflow" f0sp abort
THEN
THEN cr
;
if.forgotten fpterm
cr ." Enter: FPINIT before using!" cr